import UIKit
import Foundation

/**
 ## 示例出自：[Advanced Memory Management in Swift](https://heartbeat.comet.ml/advanced-memory-management-in-swift-4d6d9ebd7ee2)
 */

open class Employee {
  
  public var name: String
  
  public init(_ name: String) {
    self.name = name
    print("Employee \(name) initialised 🥳")
  }
  
  deinit {
    print("Employee \(name) de-initialised 💀")
  }
}

class Manager: Employee {
  var workers: [Worker] = []
}

//class Worker: Employee {
//  
//  let manager: Manager
//  
//  init(_ name: String, manager: Manager) {
//    self.manager = manager
//    super.init(name)
//  }
//}


class Worker: Employee {
  
  unowned let manager: Manager
  
  init(_ name: String, manager: Manager) {
    self.manager = manager
    super.init(name)
  }
}

struct APFactory {
    var worker: Worker?
}

do {
    let manager = Manager("Manager 1")
    let worker = Worker("Worker 1", manager: manager)
    
    var factory = APFactory(worker: worker)
    factory.worker = nil

    manager.workers.append(worker)
    print(manager.name, "is still in memory!")
    print(worker.name, "is still in memory!")
    print("worker.manager is", worker.manager)
    
}


/// -------
///
///


var tickCount = 0

let incrementTickCount : () -> Void = {
    tickCount += 1
    print("Number of ticks =", tickCount)
}

incrementTickCount()
incrementTickCount()
incrementTickCount()
incrementTickCount()


/// ----
///
///


class Person {

    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
        print("\(name) Initialised")
    }

    deinit {
        print("\(name) De-initialised")
    }

    lazy var growOld: (Int) -> Void = { by in
        self.age += by
        print(self.age)
    }
}

let mark = Person(name: "Mark", age: 10)
mark.growOld(3)
mark.growOld(6)


/// ------- 上面的deinit未走
///
///


var currentYear = 2019
let printCurrentYear = {
    print("We are in year =", currentYear)
}

printCurrentYear()


currentYear = 2020
printCurrentYear()


/// -------
///
///


let printCurrentYearUsingClosureList = { [currentYear] in
    print("Using closure lists, we are in year =", currentYear)
}
currentYear = 2021
printCurrentYearUsingClosureList()

//currentYear = 2022
//printCurrentYearUsingClosureList()

currentYear = 2022
let printCurrentYearWithOutShadow = { [curYear = currentYear, nextYear = currentYear + 1] in
    print("We are in year =", curYear, "and next year is =", nextYear)

}
printCurrentYearWithOutShadow()
currentYear = 2024
printCurrentYearWithOutShadow()


/// -------
///
///


class Year {

    var currentYear: String
    init(currentYear: String) {
        self.currentYear = currentYear
    }

    deinit {
        print("Year de-initialised")
    }

    func getYear() { print("Current year is =", currentYear) }
}

var getCurrentYear : () -> Void
do {
    let year = Year(currentYear: "2019")
//    getCurrentYear = { [curYear = year] in
//        curYear.getYear()
//    }
    
    getCurrentYear = { [weak curYear = year] in
        guard let currYear = curYear else {
            print("Unknown year ")
            return
        }
        currYear.getYear()
    }

    getCurrentYear()
    year.currentYear = "2020"
    getCurrentYear()
}
getCurrentYear()
